package cn.com.anypay.manager.payment.factory;

import cn.com.anypay.manager.payment.channel.channeltest1.impl1.ChannelTest1PaymentChannelImpl1Strategy;
import cn.com.anypay.manager.payment.channel.channeltest1.impl2.ChannelTest1PaymentChannelImpl2Strategy;
import cn.com.anypay.manager.payment.channel.channeltest2.ChannelTest2PaymentChannelStrategy;
import cn.com.anypay.manager.payment.config.ChannelConfig;
import cn.com.anypay.manager.payment.config.TestChannelConfig;
import cn.com.anypay.manager.payment.core.IPaymentChannel;
import cn.com.anypay.manager.payment.core.PaymentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * 支付渠道工厂 - 不再使用@Component
 * 由PaymentManager统一管理生命周期
 *
 * 负责创建和配置支付渠道实例，使用工厂模式实现渠道的创建逻辑
 *
 * @author AnyPay Team
 * @version 1.0
 * @since 2025-07-05
 */
public class PaymentChannelFactory {  // 移除 @Component

    private static final Logger logger = LoggerFactory.getLogger(PaymentChannelFactory.class);

    /**
     * 渠道创建器映射
     * Key: channelId_implementationType
     */
    private final Map<String, Function<ChannelConfig, IPaymentChannel>> channelCreators = new HashMap<>();

    /**
     * 渠道实现类型映射
     * Key: channelId, Value: List of implementationType
     */
    private final Map<String, List<String>> channelImplementations = new HashMap<>();

    /**
     * 默认实现映射
     * Key: channelId, Value: defaultImplementationType
     */
    private final Map<String, String> defaultImplementations = new HashMap<>();

    /**
     * 初始化状态
     */
    private volatile boolean initialized = false;

    /**
     * 构造函数，注册所有可用的渠道创建器
     */
    public PaymentChannelFactory() {
        registerChannelCreators();
    }

    /**
     * 初始化方法 - 由PaymentManager调用
     */
    public void initialize() {
        if (initialized) {
            logger.warn("PaymentChannelFactory already initialized");
            return;
        }

        logger.debug("=== PaymentChannelFactory 初始化 ===");
        // 构造函数中已经注册了渠道创建器，这里不需要额外操作
        initialized = true;
        logger.debug("PaymentChannelFactory 初始化完成");
    }

    /**
     * 销毁方法 - 由PaymentManager调用
     */
    public void destroy() {
        logger.debug("=== PaymentChannelFactory 销毁 ===");

        // 清理资源
        channelCreators.clear();
        channelImplementations.clear();
        defaultImplementations.clear();
        initialized = false;

        logger.debug("PaymentChannelFactory 销毁完成");
    }

    /**
     * 注册渠道创建器
     */
    private void registerChannelCreators() {
        // 注册测试渠道1 impl1
        channelCreators.put("channeltest1_impl1", config -> {
            if (config != null) {
                return new ChannelTest1PaymentChannelImpl1Strategy(config);
            } else {
                return new ChannelTest1PaymentChannelImpl1Strategy();
            }
        });

        // 注册测试渠道1 impl2
        channelCreators.put("channeltest1_impl2", config -> {
            if (config != null) {
                return new ChannelTest1PaymentChannelImpl2Strategy(config);
            } else {
                return new ChannelTest1PaymentChannelImpl2Strategy();
            }
        });

        // 注册测试渠道2 default实现
        channelCreators.put("channeltest2_default", config -> {
            if (config != null) {
                return new ChannelTest2PaymentChannelStrategy(config);
            } else {
                return new ChannelTest2PaymentChannelStrategy();
            }
        });

        // 设置渠道实现类型映射
        channelImplementations.put("channeltest1", Arrays.asList("impl1", "impl2"));
        channelImplementations.put("channeltest2", Arrays.asList("default"));

        // 设置默认实现映射
        defaultImplementations.put("channeltest1", "impl1");
        defaultImplementations.put("channeltest2", "default");

        logger.info("注册渠道创建器完成，支持的渠道: {}", channelCreators.keySet());
        logger.info("渠道实现映射: {}", channelImplementations);
        logger.info("默认实现映射: {}", defaultImplementations);
    }

    /**
     * 创建支付渠道实例
     *
     * @param channelId 渠道ID
     * @param config 渠道配置
     * @return 渠道实例
     * @throws PaymentException 创建失败时抛出
     */
    public IPaymentChannel createChannel(String channelId, ChannelConfig config) throws PaymentException {
        if (channelId == null || channelId.trim().isEmpty()) {
            throw new PaymentException("CREATE_CHANNEL_ERROR", "Channel ID is null or empty");
        }

        Function<ChannelConfig, IPaymentChannel> creator = channelCreators.get(channelId.toLowerCase());
        if (creator == null) {
            throw new PaymentException("CREATE_CHANNEL_ERROR", "Unsupported channel: " + channelId);
        }

        try {
            logger.info("正在创建渠道实例: {}", channelId);

            IPaymentChannel channel = creator.apply(config);
            if (channel == null) {
                throw new PaymentException("CREATE_CHANNEL_ERROR", "Failed to create channel instance: " + channelId);
            }

            logger.info("渠道实例创建成功: {} ({})", channelId, channel.getChannelName());
            return channel;

        } catch (Exception e) {
            logger.error("创建渠道实例失败: {}", channelId, e);
            if (e instanceof PaymentException) {
                throw e;
            }
            throw new PaymentException("CREATE_CHANNEL_ERROR", "Failed to create channel: " + channelId, e, channelId);
        }
    }

    /**
     * 创建测试渠道配置
     *
     * @param channelId 渠道ID
     * @return 测试配置
     */
    public ChannelConfig createTestConfig(String channelId) {
        return createTestConfig(channelId, new HashMap<>());
    }

    /**
     * 创建测试渠道配置
     *
     * @param channelId 渠道ID
     * @param customParams 自定义参数
     * @return 测试配置
     */
    public ChannelConfig createTestConfig(String channelId, Map<String, Object> customParams) {
        String channelName = getChannelName(channelId);
        TestChannelConfig config = new TestChannelConfig(channelId, channelName);

        // 设置自定义参数
        if (customParams != null && !customParams.isEmpty()) {
            for (Map.Entry<String, Object> entry : customParams.entrySet()) {
                config.setConfigParam(entry.getKey(), entry.getValue());
            }
        }

        return config;
    }

    /**
     * 批量创建渠道实例
     *
     * @param channelIds 渠道ID数组
     * @return 渠道实例映射
     */
    public Map<String, IPaymentChannel> createChannels(String[] channelIds) {
        Map<String, IPaymentChannel> channels = new HashMap<>();

        if (channelIds != null) {
            for (String channelId : channelIds) {
                try {
                    IPaymentChannel channel = createChannel(channelId, null);
                    channels.put(channelId, channel);
                } catch (PaymentException e) {
                    logger.error("创建渠道 {} 失败: {}", channelId, e.getMessage());
                }
            }
        }

        return channels;
    }

    /**
     * 检查是否支持指定渠道
     *
     * @param channelId 渠道ID
     * @return 是否支持
     */
    public boolean isChannelSupported(String channelId) {
        if (channelId == null || channelId.trim().isEmpty()) {
            return false;
        }
        return channelCreators.containsKey(channelId.toLowerCase());
    }

    /**
     * 获取所有支持的渠道ID
     *
     * @return 渠道ID数组
     */
    public String[] getSupportedChannelIds() {
        return channelCreators.keySet().toArray(new String[0]);
    }

    /**
     * 获取支持的渠道数量
     *
     * @return 渠道数量
     */
    public int getSupportedChannelCount() {
        return channelCreators.size();
    }

    /**
     * 根据渠道ID获取渠道名称
     *
     * @param channelId 渠道ID
     * @return 渠道名称
     */
    private String getChannelName(String channelId) {
        switch (channelId.toLowerCase()) {
            case "channeltest1":
                return "测试渠道1";
            case "channeltest2":
                return "测试渠道2";
            default:
                return channelId;
        }
    }

    /**
     * 注册新的渠道创建器
     *
     * @param channelId 渠道ID
     * @param creator 创建器函数
     */
    public void registerChannelCreator(String channelId, Function<ChannelConfig, IPaymentChannel> creator) {
        if (channelId != null && creator != null) {
            channelCreators.put(channelId.toLowerCase(), creator);
            logger.info("注册新的渠道创建器: {}", channelId);
        }
    }

    /**
     * 移除渠道创建器
     *
     * @param channelId 渠道ID
     * @return 是否成功移除
     */
    public boolean removeChannelCreator(String channelId) {
        if (channelId != null) {
            Function<ChannelConfig, IPaymentChannel> removed = channelCreators.remove(channelId.toLowerCase());
            if (removed != null) {
                logger.info("移除渠道创建器: {}", channelId);
                return true;
            }
        }
        return false;
    }

    /**
     * 获取渠道的实现类型列表
     *
     * @param channelId 渠道ID
     * @return 实现类型列表
     */
    public List<String> getChannelImplementations(String channelId) {
        return channelImplementations.get(channelId);
    }

    /**
     * 获取渠道的默认实现类型
     *
     * @param channelId 渠道ID
     * @return 默认实现类型
     */
    public String getDefaultImplementation(String channelId) {
        return defaultImplementations.get(channelId);
    }

    /**
     * 获取所有渠道的实现映射
     *
     * @return 渠道实现映射
     */
    public Map<String, List<String>> getAllChannelImplementations() {
        return new HashMap<>(channelImplementations);
    }

    /**
     * 获取所有渠道的默认实现映射
     *
     * @return 默认实现映射
     */
    public Map<String, String> getAllDefaultImplementations() {
        return new HashMap<>(defaultImplementations);
    }

    /**
     * 创建指定渠道的特定实现
     *
     * @param channelId 渠道ID
     * @param implementationType 实现类型
     * @return 渠道实例
     * @throws PaymentException 创建失败时抛出
     */
    public IPaymentChannel createChannelImplementation(String channelId, String implementationType) throws PaymentException {
        return createChannelImplementation(channelId, implementationType, null);
    }

    /**
     * 创建指定渠道的特定实现
     *
     * @param channelId 渠道ID
     * @param implementationType 实现类型
     * @param config 渠道配置
     * @return 渠道实例
     * @throws PaymentException 创建失败时抛出
     */
    public IPaymentChannel createChannelImplementation(String channelId, String implementationType, ChannelConfig config) throws PaymentException {
        if (channelId == null || channelId.trim().isEmpty()) {
            throw new PaymentException("CREATE_CHANNEL_ERROR", "Channel ID is null or empty");
        }

        if (implementationType == null || implementationType.trim().isEmpty()) {
            throw new PaymentException("CREATE_CHANNEL_ERROR", "Implementation type is null or empty");
        }

        String key = channelId.toLowerCase() + "_" + implementationType.toLowerCase();
        Function<ChannelConfig, IPaymentChannel> creator = channelCreators.get(key);
        if (creator == null) {
            throw new PaymentException("CREATE_CHANNEL_ERROR", "Unsupported channel implementation: " + key);
        }

        try {
            logger.debug("正在创建渠道实现: {}_{}", channelId, implementationType);

            IPaymentChannel channel = creator.apply(config);
            if (channel == null) {
                throw new PaymentException("CREATE_CHANNEL_ERROR", "Failed to create channel implementation: " + key);
            }

            logger.debug("渠道实现创建成功: {}_{} ({})", channelId, implementationType, channel.getChannelName());
            return channel;

        } catch (Exception e) {
            logger.error("创建渠道实现失败: {}_{}", channelId, implementationType, e);
            if (e instanceof PaymentException) {
                throw e;
            }
            throw new PaymentException("CREATE_CHANNEL_ERROR", "Failed to create channel implementation: " + key, e, channelId);
        }
    }

    /**
     * 检查是否支持指定的渠道实现
     *
     * @param channelId 渠道ID
     * @param implementationType 实现类型
     * @return 是否支持
     */
    public boolean isChannelImplementationSupported(String channelId, String implementationType) {
        if (channelId == null || implementationType == null) {
            return false;
        }

        String key = channelId.toLowerCase() + "_" + implementationType.toLowerCase();
        return channelCreators.containsKey(key);
    }
}